package com.prevpn.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.prevpn.api.AppApi;
import com.prevpn.common.CommonResponse;
//import com.prevpn.dto.ResourceAssignByNameDTO;
import com.prevpn.dto.TunnelAppDTO;
import com.prevpn.dto.WebAppDTO;
import com.prevpn.service.AppService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class AppServiceImpl implements AppService {

    @Autowired
    private AppApi appApi;

    /**
     * 新增 Web 应用
     * @param webAppDTO Web 应用参数
     * @return CommonResponse 封装 traceId 与新建应用 ID
     */
    @Override
    public CommonResponse<Map<String, Object>> createWebApp(WebAppDTO webAppDTO) {
        CommonResponse<Map<String, Object>> resp = new CommonResponse<>();

        // ✅ 参数基础校验
        if (webAppDTO == null ||
                StrUtil.isBlank(webAppDTO.getName()) ||
                StrUtil.isBlank(webAppDTO.getAppAddress()) ||
                StrUtil.isBlank(webAppDTO.getAccessAddress()) ||
                StrUtil.isBlank(webAppDTO.getAccessEntry()) ||
                (StrUtil.isBlank(webAppDTO.getGroupId()) && StrUtil.isBlank(webAppDTO.getGroupName())) ||
                (StrUtil.isBlank(webAppDTO.getNodeGroupId()) && StrUtil.isBlank(webAppDTO.getNodeGroupName()))) {

            resp.setCode("400");
            resp.setMsg("参数不完整：name、appAddress、accessAddress、accessEntry、groupId/groupName、nodeGroupId/nodeGroupName 必填");
            return resp;
        }

        // ✅ 序列化请求体
        String jsonBody = JSONUtil.toJsonStr(webAppDTO);

        // ✅ 调用 OpenAPI
        CommonResponse<Map<String, Object>> apiResp = appApi.createWebApp(jsonBody);

        // ✅ 返回统一结构
        resp.setCode(apiResp.getCode());
        resp.setMsg(apiResp.getMsg());
        resp.setTraceId(apiResp.getTraceId());
        resp.setData(apiResp.getData());
        return resp;
    }

     /**
      * 新增隧道应用
      * @param tunnelAppDTO 隧道应用参数
      * @return CommonResponse 封装 traceId 与新建应用 ID
      */
     @Override
     public CommonResponse<Map<String, Object>> createTunnelApp(TunnelAppDTO tunnelAppDTO) {
         CommonResponse<Map<String, Object>> resp = new CommonResponse<>();

         // ✅ 参数校验
         if (tunnelAppDTO == null ||
                 StrUtil.isBlank(tunnelAppDTO.getName()) ||
                 (StrUtil.isBlank(tunnelAppDTO.getGroupId()) && StrUtil.isBlank(tunnelAppDTO.getGroupName())) ||
                 (StrUtil.isBlank(tunnelAppDTO.getNodeGroupId()) && StrUtil.isBlank(tunnelAppDTO.getNodeGroupName())) ||
                 tunnelAppDTO.getAddressList() == null || tunnelAppDTO.getAddressList().isEmpty()) {

             resp.setCode("400");
             resp.setMsg("参数不完整：name、groupId/groupName、nodeGroupId/nodeGroupName、addressList 必填");
             return resp;
         }

         // ✅ JSON序列化并调用 OpenAPI
         String jsonBody = JSONUtil.toJsonStr(tunnelAppDTO);
         CommonResponse<Map<String, Object>> apiResp = appApi.createTunnelApp(jsonBody);

         // ✅ 统一封装响应
         resp.setCode(apiResp.getCode());
         resp.setMsg(apiResp.getMsg());
         resp.setTraceId(apiResp.getTraceId());
         resp.setData(apiResp.getData());
         return resp;
     }

    // /**
    //  * 基于应用名称授权（角色、用户或组织架构）
    //  * @param dto 请求体
    //  * @return CommonResponse
    //  */
    //@Override
    //public CommonResponse<Map<String, Object>> assignByName(ResourceAssignByNameDTO dto) {
    //    CommonResponse<Map<String, Object>> resp = new CommonResponse<>();
    //
    //    // ✅ 参数校验
    //    if (dto == null || StrUtil.isBlank(dto.getName())) {
    //        resp.setCode("400");
    //        resp.setMsg("应用名称 name 不能为空");
    //        return resp;
    //    }
    //
    //    if (dto.getData() == null ||
    //            (dto.getData().getUser() == null &&
    //                    dto.getData().getUserGroup() == null &&
    //                    dto.getData().getUserBand() == null)) {
    //        resp.setCode("400");
    //        resp.setMsg("授权对象 data 至少包含 user / userGroup / userBand 之一");
    //        return resp;
    //    }
    //
    //    // ✅ 调用 OpenAPI
    //    String jsonBody = JSONUtil.toJsonStr(dto);
    //    CommonResponse<Map<String, Object>> apiResp = appApi.assignByName(jsonBody);
    //
    //    // ✅ 封装返回
    //    resp.setCode(apiResp.getCode());
    //    resp.setMsg(apiResp.getMsg());
    //    resp.setTraceId(apiResp.getTraceId());
    //    resp.setData(apiResp.getData());
    //    return resp;
    //}

     /**
     * 基于应用名称查询详情
     * @param name 应用名称
     * @return CommonResponse
     */
    @Override
    public CommonResponse<Map<String, Object>> queryAppByName(String name) {
        CommonResponse<Map<String, Object>> resp = new CommonResponse<>();

        // ✅ 参数检查
        if (StrUtil.isBlank(name)) {
            resp.setCode("400");
            resp.setMsg("应用名称不能为空");
            return resp;
        }

        // ✅ 调用 API 层
        CommonResponse<Map<String, Object>> apiResp = appApi.queryAppByName(name);

        // ✅ 统一返回封装
        resp.setCode(apiResp.getCode());
        resp.setMsg(apiResp.getMsg());
        resp.setTraceId(apiResp.getTraceId());
        resp.setData(apiResp.getData());
        return resp;
    }

        /**
     * 查询应用列表
     * @param body 查询参数
     * @return CommonResponse
     */
    @Override
    public CommonResponse<Map<String, Object>> queryAppList(Map<String, Object> body) {
        CommonResponse<Map<String, Object>> resp = new CommonResponse<>();

        // 1️⃣ 参数检查
        if (body == null) {
            resp.setCode("400");
            resp.setMsg("参数不能为空");
            return resp;
        }

        // 2️⃣ 分页参数：默认 pageSize=10, pageIndex=1
        int pageSize = parseIntOrDefault(body.get("pageSize"), 10);
        int pageIndex = parseIntOrDefault(body.get("pageIndex"), 1);

        // 3️⃣ 模糊搜索：filter、searchValue 默认 all / 空字符串
        String filter = body.containsKey("filter") ? body.get("filter").toString() : "all";
        String searchValue = body.containsKey("searchValue") ? body.get("searchValue").toString() : "";

        // 4️⃣ 应用分类过滤：groupId 或 groupName
        if (body.containsKey("groupId")) {
            body.put("groupId", body.get("groupId").toString());
        } else if (body.containsKey("groupName")) {
            body.put("groupName", body.get("groupName").toString());
        }

        // 5️⃣ 分页与过滤参数补全
        body.put("pageSize", pageSize);
        body.put("pageIndex", pageIndex);
        body.put("filter", filter);
        body.put("searchValue", searchValue);
        body.put("isPaged", 1); // 启用分页

        // 6️⃣ 调用 aTrust OpenAPI
        return appApi.queryAppList(body);
    }

    /**
     * 工具方法：安全转换数字
     */
    private int parseIntOrDefault(Object value, int defaultVal) {
        if (value == null) return defaultVal;
        if (value instanceof Number) return ((Number) value).intValue();
        try {
            return Integer.parseInt(value.toString());
        } catch (Exception e) {
            return defaultVal;
        }
    }

    /**
     * 批量删除应用（带存在性校验）
     */
    @Override
    public CommonResponse<Map<String, Object>> deleteAppResource(Map<String, Object> body) {
        CommonResponse<Map<String, Object>> resp = new CommonResponse<>();

        if (body == null) {
            resp.setCode("400");
            resp.setData(null);
            resp.setMsg("参数不能为空");
        }

        List<String> idList = (List<String>) body.get("idList");
        List<String> nameList = (List<String>) body.get("nameList");

        if ((idList == null || idList.isEmpty()) && (nameList == null || nameList.isEmpty())) {
            resp.setCode("400");
            resp.setData(null);
            resp.setMsg("参数不完整：idList 或 nameList 至少传一个");
        }

        // ✅ 第一步：先查询现有的应用列表
        CommonResponse<Map<String, Object>> queryResp = appApi.queryAppList(Collections.emptyMap());
        if (!"OK".equalsIgnoreCase(queryResp.getCode()) && !"0".equals(queryResp.getCode())) {
            resp.setCode("500");
            resp.setData(null);
            resp.setMsg("查询应用列表失败：" + queryResp.getMsg());
            return resp;
        }

        // 提取所有存在的 name 和 id
        List<Map<String, Object>> appList = (List<Map<String, Object>>) queryResp.getData().get("data");
        Set<String> existingNames = appList.stream()
                .map(app -> (String) app.get("name"))
                .collect(Collectors.toSet());
        Set<String> existingIds = appList.stream()
                .map(app -> (String) app.get("id"))
                .collect(Collectors.toSet());

        // ✅ 第二步：检查不存在的项
        List<String> notExist = new ArrayList<>();
        if (idList != null && !idList.isEmpty()) {
            for (String id : idList) {
                if (!existingIds.contains(id)) {
                    notExist.add(id);
                }
            }
        } else {
            for (String name : nameList) {
                if (!existingNames.contains(name)) {
                    notExist.add(name);
                }
            }
        }

        // ✅ 第三步：如果有不存在的应用，直接返回错误信息
        if (!notExist.isEmpty()) {
            Map<String, Object> errData = new HashMap<>();
            errData.put("notExistList", notExist);
            resp.setCode("404");
            resp.setData(errData);
            resp.setMsg("以下应用不存在：" + String.join(", ", notExist));
            return resp;
        }

        // ✅ 第四步：全部存在时再执行删除操作
        String jsonBody = JSONUtil.toJsonStr(body);
        CommonResponse<Map<String, Object>> apiResp = appApi.deleteAppResource(jsonBody);

        // ✅ 返回统一结构
        resp.setCode(apiResp.getCode());
        resp.setMsg(apiResp.getMsg());
        resp.setTraceId(apiResp.getTraceId());
        resp.setData(apiResp.getData());
        return resp;
    }

    /**
     * 编辑 WEB 应用
     */
    @Override
    public CommonResponse<Map<String, Object>> updateWebApp(Map<String, Object> body) {
        CommonResponse<Map<String, Object>> resp = new CommonResponse<>();

        // ✅ 参数校验
        if (body == null) {
            resp.setCode("400");
            resp.setData(null);
            resp.setMsg("参数不能为空");
            return resp;
        }

        String id = (String) body.get("id");
        String name = (String) body.get("name");
        String accessEntry = (String) body.get("accessEntry");

        // id 与 name 至少一个必填
        if (StrUtil.isBlank(id) && StrUtil.isBlank(name)) {
            resp.setCode("400");
            resp.setData(null);
            resp.setMsg("参数不完整：id 或 name 至少填写一个");
            return resp;
        }

        // accessEntry 是必填字段（根据接口文档）
        if (StrUtil.isBlank(accessEntry)) {
            resp.setCode("400");
            resp.setData(null);
            resp.setMsg("参数不完整：accessEntry 必须填写");
            return resp;
        }

        // ✅ JSON 序列化
        String jsonBody = JSONUtil.toJsonStr(body);

        // ✅ 调用 OpenAPI
        CommonResponse<Map<String, Object>> apiResp = appApi.updateWebApp(jsonBody);

        // ✅ 返回统一格式
        resp.setCode(apiResp.getCode());
        resp.setMsg(apiResp.getMsg());
        resp.setTraceId(apiResp.getTraceId());
        resp.setData(apiResp.getData());
        return resp;
    }


    /**
     * 编辑 隧道应用
     */
    @Override
    public CommonResponse<Map<String, Object>> updateTunnelApp(Map<String, Object> body) {
        CommonResponse<Map<String, Object>> resp = new CommonResponse<>();
        // === 基础校验 ===
        if (body == null) {
            resp.setCode("400");
            resp.setData(null);
            resp.setMsg("参数不能为空");
            return resp;
        }

        // id 可选，但 name 必须（根据文档：只传 name 时按名称查找，但无法修改名称；若想改名需同时带 id）
        String id = body.get("id") == null ? null : String.valueOf(body.get("id"));
        String name = body.get("name") == null ? null : String.valueOf(body.get("name"));
        if (StrUtil.isBlank(name)) {
            resp.setCode("400");
            resp.setData(null);
            resp.setMsg("参数不完整：name 必须填写");
            return resp;
        }

        // 子访问模式（可选），但若传了需要是 L3VPN 或 TUN2WEB
        String subModel = body.get("subModel") == null ? null : String.valueOf(body.get("subModel"));
        if (StrUtil.isNotBlank(subModel)) {
            String sm = subModel.trim().toUpperCase();
            if (!("L3VPN".equals(sm) || "TUN2WEB".equals(sm))) {
                resp.setCode("400");
                resp.setData(null);
                resp.setMsg("subModel 非法：仅支持 L3VPN 或 TUN2WEB");
                return resp;
            }
        }

        // 校验：TUN2WEB 场景需要证书（trustedCertId / trustedCertName 至少一个）
        if ("TUN2WEB".equalsIgnoreCase(subModel)) {
            boolean hasCertId = body.containsKey("trustedCertId") && StrUtil.isNotBlank(String.valueOf(body.get("trustedCertId")));
            boolean hasCertName = body.containsKey("trustedCertName") && StrUtil.isNotBlank(String.valueOf(body.get("trustedCertName")));
            if (!hasCertId && !hasCertName) {
                resp.setCode("400");
                resp.setData(null);
                resp.setMsg("TUN2WEB 模式下需要指定 trustedCertId 或 trustedCertName");
                return resp;
            }
        }

        // 校验：TCP 协议优先走长隧道 与 地址伪装(Fake IP) 互斥（参考你之前遇到的 7201 报错）
        // ext.enableTCPPrefL3 = true 且 ext.addrPretend = true => 冲突
        if (body.containsKey("ext") && body.get("ext") instanceof Map) {
            Map<?, ?> ext = (Map<?, ?>) body.get("ext");
            Object tcpPref = ext.get("enableTCPPrefL3");
            Object addrPretend = ext.get("addrPretend");
            boolean tcpPrefEnabled = tcpPref instanceof Boolean ? (Boolean) tcpPref
                    : (tcpPref != null && "1".equals(String.valueOf(tcpPref)));
            boolean addrPretendEnabled = addrPretend instanceof Boolean ? (Boolean) addrPretend
                    : (addrPretend != null && "1".equals(String.valueOf(addrPretend)));
            if (tcpPrefEnabled && addrPretendEnabled) {
                resp.setCode("7201");
                resp.setData(null);
                resp.setMsg("TCP 长隧道与地址伪装不能同时启用，请关闭 addrPretend 或取消 enableTCPPrefL3");
                return resp;
            }
        }

        // 注意：ext / openModel 不支持增量修改。若前端传了它们，必须是全量对象。
        // 这里不做字段级别深度校验，直接透传给后端，后端会给出更准确的错误码/提示。

        // === 调用 OpenAPI ===
        String jsonBody = JSONUtil.toJsonStr(body);
        CommonResponse<Map<String, Object>> apiResp = appApi.updateTunnelApp(jsonBody);

        // === 返回统一结构 ===
        resp.setCode(apiResp.getCode());
        resp.setMsg(apiResp.getMsg());
        resp.setTraceId(apiResp.getTraceId());
        resp.setData(apiResp.getData());
        return resp;
    }

}
